package com.wnxy.mallserver.service.impl;

import com.wnxy.mallserver.entity.Address;
import com.wnxy.mallserver.entity.Goods;
import com.wnxy.mallserver.entity.Order;
import com.wnxy.mallserver.entity.OrderItem;
import com.wnxy.mallserver.mapper.OrderMapper;
import com.wnxy.mallserver.response.Prefix;
import com.wnxy.mallserver.service.*;
import com.wnxy.mallserver.util.SnowflakeIdWorker;
import com.wnxy.mallserver.vo.CartVo;
import com.wnxy.mallserver.vo.order.AddOrderVo;
import com.wnxy.mallserver.vo.order.OrderInfoVo;
import com.wnxy.mallserver.vo.order.OrderVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    /**
     * 注入订单的mapper
     */
    @Resource
    private OrderMapper orderMapper;
    /**
     * 注入相关service，不建议注入mapper，因为可能还存在业务逻辑
     */
    @Resource
    private CartService cartService;//注入购物车service
    @Resource
    private GoodsService goodsService; //注入商品service
    @Resource
    private AddressService addressService;//注入地址service
    @Resource
    private OrderItemService orderItemService;//注入订单详情service
    @Resource
    private RedisTemplate<String,Object> redisTemplate;//注入redis


    @Transactional
    @Override
    public OrderVo addOrder(AddOrderVo addOrderVo) {
        //1 删减商品表中的库存
        //1.1   查询本次添加到订单页面的商品信息（即通过购物车中的ids获取）
        List<CartVo> cartVoList = cartService.findByCids(addOrderVo.getCids());
        //1.2   新建一个订单详情表，用于装商品信息
        List<OrderItem> orderItems = new ArrayList<>();
        //1.3   计算商品总价
        BigDecimal totalPrice = new BigDecimal(0);

        //1.4   遍历cartVoList
        for(CartVo cartVo:cartVoList){
            //1.4.1 减库存,若库存抛异常，则后续操作不执行（参数：商品id，和库存数量）
            goodsService.updateStock(cartVo.getGid(),0 - cartVo.getNum());
            //1.4.2 计算总价：总价 = 总价 +（单价*数量）
            totalPrice = totalPrice.add(cartVo.getPrice().multiply(new BigDecimal(cartVo.getNum())));
            //1.4.3 向订单详情表添加数据
            orderItems.add(new OrderItem(cartVo.getGid(),cartVo.getName(),cartVo.getImage(),cartVo.getNum(),cartVo.getPrice()));
        }

        //2.生成订单编号
        SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(1);
        //2.1   获取编号，后续凭借一个空字符串，将雪花id变成字符串类型（long -> string）
        String no = snowflakeIdWorker.nextId() + "";

        //3.通过地址id查询收货人地址信息
        Address address = addressService.findByAid(addOrderVo.getAid());
            //省市区详细地址
        String pccd = address.getProvince() + address.getCity() + address.getCounty() + address.getDetailaddress();

        //4.封装订单信息--向订单表中插入信息
        Order order = new Order(null,no,addOrderVo.getUid(),totalPrice,null,pccd,address.getAccept(),address.getCellphone(),null,null);
        orderMapper.addOrder(order);

        //5.向订单详情表插入订单与商品的关联信息，由订单id获取
        orderItems.forEach(item -> {//遍历订单详情，将订单id注入
            item.setOid(order.getId());
        });
        orderItemService.addOrderItem(orderItems);

        //6.删减购物车中的被勾选的信息
        cartService.delByIds(addOrderVo.getCids());

        //7.超时处理--15min
        redisTemplate.opsForValue().set(Prefix.ORDER + no,null,15, TimeUnit.MINUTES);

        //8.封装订单信息，返回给前端。（订单的编号，金额和名称）
        String name = UUID.randomUUID().toString();
        OrderVo orderVo = new OrderVo(no,totalPrice, name,"测试商品信息");
        return orderVo;
    }

    /**
     * 处理超时订单
     * 1.修改订单状态
     * 2.返还库存数量
     **/
    @Override
    public void expire(String orderno) {
        //修改订单状态
        if(orderMapper.updateState(orderno)){//修改成功，表明未成功下单，此时应该归还商品库存
           //1.获取订单id
            int oid = orderMapper.findIdByOrderno(orderno);
            //2.通过订单id查询订单详情表，得到商品id以及数量
            List<OrderItem> orderItems = orderItemService.findByOid(oid);
            //3.通过商品id中的数量，返还给库存
            orderItems.forEach(orderItem -> {
                goodsService.updateStock(orderItem.getGid(),orderItem.getNum());
            });

        }
    }

    @Transactional
    @Override
    public void addKillOrder(Order order) {
        orderMapper.addOrder(order);
    }

    @Override
    public OrderInfoVo findByOrderno(String orderno) {
        return null;
//        return orderMapper.findByOrderno(orderno);
    }
}


























